package com.loyal.camerax.ui

import android.app.Activity
import android.util.Log
import android.widget.ImageButton
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.view.CameraController.OutputSize
import androidx.camera.view.LifecycleCameraController
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.window.layout.WindowMetrics
import androidx.window.layout.WindowMetricsCalculator
import com.loyal.camerax.R
import com.loyal.camerax.annotation.TorchFlashState
import com.loyal.camerax.config.PhotoConfig
import com.loyal.camerax.ui.base.BaseCameraActivity
import com.loyal.camerax.utils.ControllerHelper.hasBackCamera
import com.loyal.camerax.utils.ControllerHelper.hasFrontCamera
import com.loyal.camerax.utils.ControllerHelper.switchCameraSelector
import com.loyal.camerax.utils.ControllerHelper.takePhotoByByteArray
import com.loyal.camerax.utils.aspectRatio
import com.loyal.camerax.utils.touchFocus
import com.loyal.camerax.utils.observeCameraState
import com.loyal.camerax.utils.removeObservers
import kotlinx.coroutines.launch
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.Executor

class LifecycleCameraActivity : BaseCameraActivity() {

    private lateinit var windowMetrics: WindowMetrics
    private lateinit var cameraExecutor: Executor
    private var controller: LifecycleCameraController? = null

    override fun initCamerax() {
        cameraExecutor = ContextCompat.getMainExecutor(this)

        windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        binding.previewView.apply {
            post {
                setCameraUI()
                lifecycleScope.launch {
                    setUpCamera()
                }
            }
        }
    }

    private fun setUpCamera() {
        controller = LifecycleCameraController(this)
        bindCameraUseCases()
        stateCallback()
    }

    override fun stateCallback() {
        controller?.let {
            //聚焦
            it.tapToFocusState.observe(this) { state ->
                Log.e(TAG, "tapToFocusState: $state")
                binding.focusView.focusStateChanged(state)
            }
            binding.previewView.touchFocus(binding.focusView)

            //手电筒
            it.torchState.observe(this) { state ->
                Log.e(TAG, "torchState: $state")
            }

            //缩放
            it.zoomState.observe(this) { /*state ->
                Log.e(TAG, "zoomState.linearZoom: " + state.linearZoom)
                Log.e(TAG, "zoomState.minZoomRatio: " + state.minZoomRatio)
                Log.e(TAG, "zoomState.maxZoomRatio: " + state.maxZoomRatio)
                Log.e(TAG, "zoomState.zoomRatio: " + state.zoomRatio)*/
            }
        }
    }

    private fun bindCameraUseCases() {
        val metrics = windowMetrics.bounds
        val screenAspectRatio = aspectRatio(metrics.width(), metrics.height())
        val outputSize = OutputSize(screenAspectRatio.preferredAspectRatio)
        // 预览
        controller?.let {
            //预览
            it.previewTargetSize = outputSize
            // 图片分析
            it.imageAnalysisTargetSize = outputSize
            // 拍照
            it.imageCaptureTargetSize = outputSize
            it.imageCaptureMode = ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY

            it.unbind()
            it.cameraInfo?.cameraState?.removeObservers(this)

            it.initializationFuture.addListener({
                val hasBackCamera = it.hasBackCamera()
                val hasFrontCamera = it.hasFrontCamera()

                if (!hasBackCamera && !hasFrontCamera) {
                    Log.e(TAG, "Camera is unavailable!!!")
                    finish()
                    return@addListener
                }
                cameraBinding().cameraSwitch.isEnabled = hasFrontCamera && hasBackCamera

                //前后相机镜头
                it.cameraSelector = if (hasBackCamera) CameraSelector.DEFAULT_BACK_CAMERA
                else CameraSelector.DEFAULT_FRONT_CAMERA

                binding.previewView.controller = it
                it.bindToLifecycle(this)//绑定并启动相机
                it.cameraInfo.observeCameraState(this@LifecycleCameraActivity)

                val hasFlash = it.cameraInfo?.hasFlashUnit() ?: false
                if (hasFlash) {//FLASH_MODE_ON //拍照时开启
                    it.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO
                    settingsBinding().flashSwitch.isEnabled = true
                } else {
                    it.imageCaptureFlashMode = ImageCapture.FLASH_MODE_OFF
                    settingsBinding().flashSwitch.isEnabled = false
                }
            }, cameraExecutor)
        }
    }

    override fun restart(activity: Activity) {
        controller?.cameraInfo?.removeObservers(this)
        controller?.unbind()
        super.restart(activity)
    }

    override fun updateTorchFlash(view: ImageButton, @TorchFlashState value: String?): Boolean {
        val hasFlash = controller?.cameraInfo?.hasFlashUnit() ?: false
        if (!hasFlash) return false
        when (value) {
            TorchFlashState.ON, getString(R.string.flash_value_on) -> {
                controller?.imageCaptureFlashMode = ImageCapture.FLASH_MODE_ON
                controller?.enableTorch(false)
                view.setImageResource(R.drawable.flash_on)
                return true
            }

            TorchFlashState.AUTO, getString(R.string.flash_value_auto) -> {
                controller?.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO
                controller?.enableTorch(false)
                view.setImageResource(R.drawable.flash_auto)
                return true
            }

            TorchFlashState.TORCH, getString(R.string.flash_value_torch) -> {
                controller?.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO
                controller?.enableTorch(true)
                view.setImageResource(R.drawable.flash_torch)
                return true
            }

            TorchFlashState.OFF, getString(R.string.flash_value_off) -> {
                controller?.imageCaptureFlashMode = ImageCapture.FLASH_MODE_OFF
                controller?.enableTorch(false)
                view.setImageResource(R.drawable.flash_off)
                return true
            }
        }
        return false
    }

    override fun switchCamera() {
        controller?.switchCameraSelector()
    }

    override fun takePhoto() {
        val newPath = savePath().ifEmpty {
            filesDir.path
        }

        val fileName = saveName().ifEmpty {
            SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US)
                .format(System.currentTimeMillis())
        }
        val imageFile = File(newPath, "$fileName.jpg")

        val isFrontPhoto = CameraSelector.DEFAULT_FRONT_CAMERA == controller?.cameraSelector
        val config = PhotoConfig(
            horizontalMirror = isFrontPhoto,
            imageFile = imageFile,
            enableCompress = true,
        )

        controller?.takePhotoByByteArray(config, cameraExecutor) {
            if (it) setGalleryThumbnail(imageFile.path)
        }
    }

    companion object {
        private const val TAG = "LifecycleCameraActivity"
    }
}